Introduction
The field of data science is rapidly evolving, with professionals
playing pivotal roles in shaping industries across the globe.
Understanding the dynamics of job roles, salaries, and related factors
is crucial for both aspiring data scientists and organizations seeking
to attract and retain talent. In this report, we delve into insights
derived from the comprehensive dataset titled “Jobs and Salaries in Data
Science,” obtained from Kaggle.
Our analysis centers around several key questions aimed at uncovering
patterns and trends within the data science domain:
Correlation between Employee Residence and Salary
Levels: Are there discernible correlations between where data
science professionals reside and the levels of their salaries? How does
this correlation vary across different regions or countries?
Prevalence of Job Titles Across Regions: Do
certain job titles dominate specific regions or countries? By exploring
this question, we aim to discern any geographical preferences or trends
in job roles within the data science field.
Distribution of Work Experience Levels: What is
the distribution of respondents based on their years of work experience?
Understanding this distribution provides valuable insights into the
experience levels prevalent within the data science workforce.
Trends in Work Experience Levels Across
Locations: Are there notable trends in work experience levels
among data science professionals residing in different locations? By
analyzing this aspect, we aim to identify any geographical variations in
experience levels.
Trend in Salaries Across Work Years: Is there a
discernible change in the average salary across different work years
within the data science field?
Trend in Salaries Across Experience Levels: Is
there a discernible change in the average salary across different
experience levels within the data science field?
Dataset Description
The “Jobs and Salaries in Data Science” dataset is a comprehensive
compilation of information pertaining to salaries and related factors
within the data science field. It includes details such as job title,
job category, salary in various currencies, employee residence,
experience level, employment type, work setting, company location, and
company size. This rich dataset offers an invaluable resource for
analyzing salary trends, comparing salaries across roles and regions,
and understanding the factors influencing salary structures within the
data industry.
In the subsequent sections of this report, we delve deeper into each
research question, presenting our findings and interpretations derived
from the analysis of the dataset. Through this exploration, we aim to
provide actionable insights that can inform strategic decisions for both
individuals and organizations operating within the dynamic landscape of
data science.
Analysis
Scatterplot of Salary in USD by Employee Residence
# Create the ggplot object
scatterplot <- ggplot(filtered_data, aes(x = employee_residence, y = salary_in_usd, color = employee_residence)) +
geom_point(alpha = 0.5) +
labs(title = "Scatterplot of Salary in USD by Employee Residence",
x = "Employee Residence",
y = "Salary in USD") + scale_y_continuous(labels = scales::comma_format()) +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1))
# Convert ggplot object to a plotly object
interactive_scatterplot <- ggplotly(scatterplot)
interactive_scatterplot
The scatterplot provides a visual representation of the relationship
between salary and employee residence, allowing for insights into salary
distribution, regional disparities, and potential correlations. The
salaries vary significantly across different employee residences,
ranging from as low as $15,000 to as high as $323,905. Certain countries
or regions seem to have higher salary ranges compared to others. For
example, countries like France, Portugal, and Lithuania have a wide
range of salary levels, including both high and moderate salaries. There
are some instances of exceptionally high salaries, such as in France
where the salary reaches $323,905, and in New Zealand with a salary of
$125,000. Several factors could contribute to these salary differences,
including local economic conditions, cost of living, demand for specific
skills, and industry specialization in certain regions.
Prevalence of Job Titles Across Regions
# Create a stacked bar plot
interactive_stacked_bar <- filtered_data %>%
group_by(employee_residence, job_title) %>%
summarise(count = n()) %>%
ggplot(aes(x = employee_residence, y = count, fill = job_title)) +
geom_bar(stat = "identity") +
labs(title = "Prevalence of Job Titles Across Regions",
x = "Region or Country",
y = "Count",
fill = "Job Title") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
## `summarise()` has grouped output by 'employee_residence'. You can override
## using the `.groups` argument.
# Convert the ggplot object to an interactive plot
interactive_stacked_bar <- ggplotly(interactive_stacked_bar)
interactive_stacked_bar
France: Leads with a total count of 69, encompassing a
wide range of job titles including data engineering, data science, and
machine learning engineering. Portugal: Follows closely
with a total count of 27, with diverse roles in data analysis, data
engineering, and machine learning engineering. Pakistan:
Shows a smaller presence with a total count of 6, mainly in data
engineering, data science consultancy, and AI programming.
Philippines: Exhibits a limited presence with a total count
of 4, focusing on roles such as business data analysis, data science
management, and data analytics.
Belgium, Lithuania, and Turkey: Each have a moderate
presence with counts ranging from 2 to 4, primarily in roles like data
scientist, machine learning engineer, and AI scientist.
Other countries: Have minimal representation, with counts
ranging from 1 to 2, encompassing specific job titles.
Distribution of Experience Levels
# Create an interactive barplot using plot_ly
interactive_barplot <- plot_ly(data = filtered_data, x = ~experience_level, type = "histogram", marker = list(color = "brown")) %>%
layout(title = "Distribution of Experience Levels",
xaxis = list(title = "Experience Level"),
yaxis = list(title = "Frequency"))
# display the interactive barplot
interactive_barplot
The distribution of experience levels among employees in the filtered
dataset for 25 countries is as follows: there are 35 entry-level, 3
executive, 51 mid-level, and 43 senior-level positions. This
distribution provides insight into the workforce composition and
highlights the prevalence of mid-level and senior-level roles compared
to entry-level and executive positions. Understanding this distribution
can aid in workforce planning, talent management, and organizational
development strategies.
Average Salary Over Years
# Average salary over years
average_salary <- filtered_data %>%
group_by(work_year) %>%
summarise(avg_salary = mean(salary_in_usd))
# Create an interactive line plot for average salary over years
interactive_line_plot <- plot_ly(data = average_salary, x = ~work_year, y = ~avg_salary, type = "scatter", mode = "lines+markers",
line = list(color = "black")) %>%
layout(title = "Average Salary Over Years",
xaxis = list(title = "Year"),
yaxis = list(title = "Average Salary (USD)"))
# display the interactive line plot
interactive_line_plot
The graph reveals a notable increase in the average salary over the
years, reflecting potential trends in the job market or economic
conditions. In 2020, the average salary was $59.04k, showing a slight
decrese to $57.43k in 2021. However, a more significant jump occurred in
2022, with the average salary rising to $65.56k. This increase could
signify factors such as industry growth, demand for skilled
professionals, or inflationary pressures impacting compensation. The
most substantial increase is observed in 2023, where the average salary
surged to $81.09k, suggesting robust economic conditions, high demand
for talent, or advancements in specialized skills driving up
compensation levels. Overall, this analysis highlights the dynamic
nature of salary trends and underscores the importance of monitoring and
adapting to changing market conditions for both employers and
employees.
Salary Distribution by Job Title
# Create interactive boxplot for salary distribution according to job title
interactive_salary_boxplot <- plot_ly(filtered_data, x = ~job_title, y = ~salary_in_usd, type = "box") %>%
layout(title = "Salary Distribution by Job Title",
xaxis = list(title = "Job Title"),
yaxis = list(title = "Salary (USD)"))
# Print the interactive boxplot
interactive_salary_boxplot
The interactive boxplot analysis provides valuable insights into the
salary distribution across different job titles. Among the job titles
examined, “Head of Data,” “Research Engineer,” and “AI Developer” stand
out for their notable variation in salary. The boxplot illustrates
considerable variability in salaries within the roles, with some
individuals potentially earning substantially higher or lower than the
median. This variation could be attributed to factors such as years of
experience, industry specialization, or additional qualifications.
Head of Data: The median salary for this position is $137,000,
indicating a significant earning potential.
Research Engineer: With a median salary of $168,000, the role of a
Research Engineer commands considerable compensation.
AI Developer: The median salary for AI Developers is $118,000,
reflecting the demand for professionals skilled in artificial
intelligence technologies.
Salary Distribution by Experience Level
# salary distribution according to experience level
# Create interactive boxplot for salary distribution according to experience level
interactive_exp_boxplot <- plot_ly(filtered_data, x = ~experience_level, y = ~salary_in_usd, type = "box") %>%
layout(title = "Salary Distribution by Experience Level",
xaxis = list(title = "Experience Level"),
yaxis = list(title = "Salary (USD)"))
# Print the interactive boxplot
interactive_exp_boxplot
The salary distribution analysis by experience level reveals distinct
trends:
Entry Level: Median salary is $40,000, typical for new or less
experienced workers. This salary level reflects the compensation
typically offered to individuals who are new to the workforce or have
limited professional experience. Entry-level salaries may vary depending
on factors such as industry, location, and specific job roles.
Executive: Median salary jumps to $106,000, reflecting the high
responsibilities of leadership roles. Executives typically hold top
leadership positions within organizations and are responsible for
strategic decision-making and overseeing company operations. The higher
salary range for executives reflects the significant responsibilities
and leadership roles they undertake.
Mid Level: Median salary stands at $57,220, indicating moderate
experience and responsibilities. Mid-level positions often require a
moderate level of experience and expertise, with individuals assuming
roles that involve greater responsibilities and specialized skills
compared to entry-level positions. The salary reflects a midpoint
between entry-level and senior-level compensation.
Senior Level: Median salary rises to $76,050, reflecting
extensive experience and leadership roles. Senior-level roles typically
require extensive experience, specialized skills, and a track record of
leadership and accomplishments. The higher compensation reflects the
value placed on the expertise and contributions of senior professionals
to organizations.
Overall, salaries increase significantly as professionals progress
from entry to senior levels, reflecting their experience and
contributions to organizations.
Treemap of Average Salary by Employee Residence and Job Title
# Geographical salary distribution
# Group the data
grouped_data <- filtered_data %>%
group_by(employee_residence, job_title, salary_in_usd) %>%
summarise(count = n())
## `summarise()` has grouped output by 'employee_residence', 'job_title'. You can
## override using the `.groups` argument.
# Calculate average salary per group
average_salary <- grouped_data %>%
group_by(job_title, employee_residence) %>%
summarise(avg_salary = mean(salary_in_usd), .groups = 'drop')
# Create the treemap
data_science_treemap <- treemap(average_salary,
index = c("job_title", "employee_residence"),
vSize = "avg_salary",
title = "Treemap of Average Salary by Employee Residence and Job Title")

# Print the treemap
# print(data_science_treemap)
d3tree(data_science_treemap, rootname = "Jobs")
In this analysis, we generated a treemap graph along with its
interactive version, showcasing the average salary distribution
according to employee residence and job titles. The treemap
visualization allowed us to explore the salary trends across different
countries and job roles efficiently.
Upon examination of the graph, it was evident that certain job titles
commanded higher average salaries across various countries.
Specifically, roles such as ML engineer, data engineer, data scientist,
finance data analyst, data analyst, and head of data consistently
emerged with the highest average salaries.
Salary Trend for Data Scientists Over Work Years
# salary of over years
# Filter the data for Data Scientists
data_scientist_salary <- filtered_data[filtered_data$job_title == "Data Scientist", ]
# Create the scatter plot
scatter_plot <- ggplot(data_scientist_salary, aes(x = work_year, y = salary_in_usd)) +
geom_point(color = "blue", alpha = 0.5) +
labs(title = "Salary Trend for Data Scientists Over Work Years",
x = "Work Year",
y = "Salary (USD)")
# Add trend line
scatter_plot_with_trend <- scatter_plot +
geom_smooth(method = "lm", se = FALSE, color = "black", linewidth = 0.5)
# Convert to plotly object
interactive_plot <- ggplotly(scatter_plot_with_trend)
## `geom_smooth()` using formula = 'y ~ x'
# Print the interactive plot
interactive_plot
# TO CHECK IF THE TREND LINE IS INCREASING/DECREASING
# Fit a linear model to the data
lm_model <- lm(salary_in_usd ~ work_year, data = data_scientist_salary)
# Get the coefficients of the linear model and slop
coefficients <- coef(lm_model)
slope <- coefficients[2]
# Check if the slope is positive, indicating an increase over years
if (slope > 0) {
cat("The trend line indicates an increase in salaries over the years.")
} else if (slope == 0) {
cat("The trend line indicates no change in salaries over the years.")
} else {
cat("The trend line indicates a decrease in salaries over the years.")
}
## The trend line indicates an increase in salaries over the years.
Based on our analysis focusing on the data scientist role, which
appears to have the highest representation across the selected
countries, we investigated the salary trends over the years. Our
examination, as depicted in the graph and confirmed by the linear model
results, reveals a subtle but discernible increase in salary over the
years. While the upward trajectory is evident, it’s important to note
that the rate of increase appears to be minimal. This observation
suggests that while there is a positive trend in data scientist salaries
over time, the growth rate may be relatively slow. This insight
underscores the stability or modest growth in compensation for data
scientists within the selected regions over the specified period.
Results
In this study, we analyzed data from 25 randomly selected countries,
focusing on five key variables: job title, employee residence, salary in
USD, work experience, and work year. Our analysis comprised several
graphical representations, each offering insights into different aspects
of the dataset:
ChatGPT Results
In this study, we analyzed data from 25 randomly selected countries,
focusing on five key variables: job title, employee residence, salary in
USD, work experience, and work year. Our analysis comprised several
graphical representations, each offering insights into different aspects
of the dataset:
- Scatterplot Analysis: We conducted a scatterplot analysis to
visualize the relationship between employee residence and salary in
USD.
- Stacked Barplot: A stacked barplot was utilized to illustrate the
prevalence of various job titles across different employee residence
countries.
- Barplot of Experience Levels: We created a barplot depicting the
distribution of experience levels among the sampled data.
- Average Salary Over Years: A lineplot graph was generated to display
the average salary trends over the years.
- Salary Distribution by Job Title: We employed a boxplot to showcase
the distribution of salaries according to different job titles.
- Salary Distribution by Experience Level: Another boxplot was
utilized to visualize the salary distribution across various experience
levels.
- Treemap Visualization: A treemap was constructed to present the
average salary distribution by employee residence and job title.
- Salary Trend Analysis for Data Scientists: Finally, we conducted a
trend analysis specifically focusing on the salary trend for data
scientists over the years.
These graphical representations offer valuable insights into the
dataset, providing a comprehensive understanding of salary
distributions, trends, and variations across different variables and
over time.
Conclusions
In this comprehensive analysis, we delved into various aspects of
salary distribution, workforce composition, and salary trends across
different job titles, experience levels, and geographical regions.
Through interactive visualizations and statistical analyses, we gained
valuable insights into the dynamics of compensation within the
industry.
The scatterplot depicting the relationship between salary and
employee residence revealed significant variations in salary levels
across different countries, underscoring regional disparities and
potential factors influencing compensation. Furthermore, the stacked
barplot provided a clear overview of the prevalence of different job
titles across various employee residences, highlighting countries with a
high concentration of specific roles.
Examining the distribution of experience levels among employees
offered insights into the workforce composition, with a notable presence
of mid-level and senior-level positions. This distribution reflects the
maturity and expertise of the workforce, essential for understanding
talent demographics and planning organizational strategies.
The analysis of average salary trends over the years unveiled a
positive trajectory, with salaries experiencing a steady increase over
time. This growth reflects broader economic conditions, industry demand,
and evolving skill requirements contributing to salary escalations
across different job roles and regions.
The examination of salary distributions by job title and experience
level provided a nuanced understanding of compensation structures within
the industry. Roles such as Head of Data, Research Engineer, and AI
Developer emerged with notable salary variations, indicative of the
diverse skillsets and responsibilities associated with these positions.
Additionally, the analysis highlighted significant differences in
salaries across experience levels, emphasizing the importance of
expertise and seniority in driving compensation levels.
Finally, the treemap visualization offered a comprehensive view of
average salary distributions across employee residences and job titles,
highlighting lucrative roles and regions within the industry. By
focusing on the data scientist role, we observed a subtle yet
discernible increase in salary over the years, indicating stable or
modest growth in compensation for professionals within this domain.
In conclusion, this analysis provides valuable insights for industry
stakeholders, policymakers, and professionals seeking to understand
salary dynamics, workforce trends, and regional variations within the
field. By leveraging interactive visualizations and statistical
analyses, we have shed light on key factors shaping compensation trends,
offering a robust foundation for informed decision-making and strategic
planning in the ever-evolving landscape of the industry.
LS0tCnRpdGxlOiAnVW5sb2NraW5nIEluc2lnaHRzOiBFeHBsb3JpbmcgU2FsYXJ5IER5bmFtaWNzIGFuZCBFbXBsb3ltZW50IFRyZW5kcyBpbiBEYXRhIFNjaWVuY2UnCmF1dGhvcjogIktyaXNobmEgUGF0ZWwiCmRhdGU6ICJGZWJydWFyeSAyNSwgMjAyNCIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMKICAgIGZpZ19jYXB0aW9uOiB5ZXMKICAgIHRoZW1lOiBsdW1lbgogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogMgogICAgZGZfcHJpbnQ6IGthYmxlCiAgICB0b2NfZmxvYXQ6CiAgICAgIGNvbGxhcHNlZDogbm8KICBwZGZfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiAnMicKLS0tCmBgYHtyLCBtZXNzYWdlPUZBTFNFfQojIFJlcXVpcmVkIHBhY2thZ2VzIGZvciBvdXIgY291cnNlLiBEbyBub3QgZGVsZXRlLgpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShtb3NhaWMpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShwbG90bHkpCmxpYnJhcnkodHJlZW1hcCkKbGlicmFyeShkZXZ0b29scykKbGlicmFyeShodG1sd2lkZ2V0cykKbGlicmFyeShkM3RyZWVSKQpgYGAKCgojIEludHJvZHVjdGlvbgpUaGUgZmllbGQgb2YgZGF0YSBzY2llbmNlIGlzIHJhcGlkbHkgZXZvbHZpbmcsIHdpdGggcHJvZmVzc2lvbmFscyBwbGF5aW5nIHBpdm90YWwgcm9sZXMgaW4gc2hhcGluZyBpbmR1c3RyaWVzIGFjcm9zcyB0aGUgZ2xvYmUuIFVuZGVyc3RhbmRpbmcgdGhlIGR5bmFtaWNzIG9mIGpvYiByb2xlcywgc2FsYXJpZXMsIGFuZCByZWxhdGVkIGZhY3RvcnMgaXMgY3J1Y2lhbCBmb3IgYm90aCBhc3BpcmluZyBkYXRhIHNjaWVudGlzdHMgYW5kIG9yZ2FuaXphdGlvbnMgc2Vla2luZyB0byBhdHRyYWN0IGFuZCByZXRhaW4gdGFsZW50LiBJbiB0aGlzIHJlcG9ydCwgd2UgZGVsdmUgaW50byBpbnNpZ2h0cyBkZXJpdmVkIGZyb20gdGhlIGNvbXByZWhlbnNpdmUgZGF0YXNldCB0aXRsZWQgIkpvYnMgYW5kIFNhbGFyaWVzIGluIERhdGEgU2NpZW5jZSwiIG9idGFpbmVkIGZyb20gS2FnZ2xlLgoKT3VyIGFuYWx5c2lzIGNlbnRlcnMgYXJvdW5kIHNldmVyYWwga2V5IHF1ZXN0aW9ucyBhaW1lZCBhdCB1bmNvdmVyaW5nIHBhdHRlcm5zIGFuZCB0cmVuZHMgd2l0aGluIHRoZSBkYXRhIHNjaWVuY2UgZG9tYWluOgoKMS4gKipDb3JyZWxhdGlvbiBiZXR3ZWVuIEVtcGxveWVlIFJlc2lkZW5jZSBhbmQgU2FsYXJ5IExldmVsczoqKiBBcmUgdGhlcmUgZGlzY2VybmlibGUgY29ycmVsYXRpb25zIGJldHdlZW4gd2hlcmUgZGF0YSBzY2llbmNlIHByb2Zlc3Npb25hbHMgcmVzaWRlIGFuZCB0aGUgbGV2ZWxzIG9mIHRoZWlyIHNhbGFyaWVzPyBIb3cgZG9lcyB0aGlzIGNvcnJlbGF0aW9uIHZhcnkgYWNyb3NzIGRpZmZlcmVudCByZWdpb25zIG9yIGNvdW50cmllcz8KCjIuICoqUHJldmFsZW5jZSBvZiBKb2IgVGl0bGVzIEFjcm9zcyBSZWdpb25zOioqIERvIGNlcnRhaW4gam9iIHRpdGxlcyBkb21pbmF0ZSBzcGVjaWZpYyByZWdpb25zIG9yIGNvdW50cmllcz8gQnkgZXhwbG9yaW5nIHRoaXMgcXVlc3Rpb24sIHdlIGFpbSB0byBkaXNjZXJuIGFueSBnZW9ncmFwaGljYWwgcHJlZmVyZW5jZXMgb3IgdHJlbmRzIGluIGpvYiByb2xlcyB3aXRoaW4gdGhlIGRhdGEgc2NpZW5jZSBmaWVsZC4KCjMuICoqRGlzdHJpYnV0aW9uIG9mIFdvcmsgRXhwZXJpZW5jZSBMZXZlbHM6KiogV2hhdCBpcyB0aGUgZGlzdHJpYnV0aW9uIG9mIHJlc3BvbmRlbnRzIGJhc2VkIG9uIHRoZWlyIHllYXJzIG9mIHdvcmsgZXhwZXJpZW5jZT8gVW5kZXJzdGFuZGluZyB0aGlzIGRpc3RyaWJ1dGlvbiBwcm92aWRlcyB2YWx1YWJsZSBpbnNpZ2h0cyBpbnRvIHRoZSBleHBlcmllbmNlIGxldmVscyBwcmV2YWxlbnQgd2l0aGluIHRoZSBkYXRhIHNjaWVuY2Ugd29ya2ZvcmNlLgoKNC4gKipUcmVuZHMgaW4gV29yayBFeHBlcmllbmNlIExldmVscyBBY3Jvc3MgTG9jYXRpb25zOioqIEFyZSB0aGVyZSBub3RhYmxlIHRyZW5kcyBpbiB3b3JrIGV4cGVyaWVuY2UgbGV2ZWxzIGFtb25nIGRhdGEgc2NpZW5jZSBwcm9mZXNzaW9uYWxzIHJlc2lkaW5nIGluIGRpZmZlcmVudCBsb2NhdGlvbnM/IEJ5IGFuYWx5emluZyB0aGlzIGFzcGVjdCwgd2UgYWltIHRvIGlkZW50aWZ5IGFueSBnZW9ncmFwaGljYWwgdmFyaWF0aW9ucyBpbiBleHBlcmllbmNlIGxldmVscy4KCjUuICoqVHJlbmQgaW4gU2FsYXJpZXMgQWNyb3NzIFdvcmsgWWVhcnM6KiogSXMgdGhlcmUgYSBkaXNjZXJuaWJsZSBjaGFuZ2UgaW4gdGhlIGF2ZXJhZ2Ugc2FsYXJ5IGFjcm9zcyBkaWZmZXJlbnQgd29yayB5ZWFycyB3aXRoaW4gdGhlIGRhdGEgc2NpZW5jZSBmaWVsZD8KCjYuICoqVHJlbmQgaW4gU2FsYXJpZXMgQWNyb3NzIEV4cGVyaWVuY2UgTGV2ZWxzOioqIElzIHRoZXJlIGEgZGlzY2VybmlibGUgY2hhbmdlIGluIHRoZSBhdmVyYWdlIHNhbGFyeSBhY3Jvc3MgZGlmZmVyZW50IGV4cGVyaWVuY2UgbGV2ZWxzIHdpdGhpbiB0aGUgZGF0YSBzY2llbmNlIGZpZWxkPwoKIyMjIERhdGFzZXQgRGVzY3JpcHRpb24KClRoZSAiSm9icyBhbmQgU2FsYXJpZXMgaW4gRGF0YSBTY2llbmNlIiBkYXRhc2V0IGlzIGEgY29tcHJlaGVuc2l2ZSBjb21waWxhdGlvbiBvZiBpbmZvcm1hdGlvbiBwZXJ0YWluaW5nIHRvIHNhbGFyaWVzIGFuZCByZWxhdGVkIGZhY3RvcnMgd2l0aGluIHRoZSBkYXRhIHNjaWVuY2UgZmllbGQuIEl0IGluY2x1ZGVzIGRldGFpbHMgc3VjaCBhcyBqb2IgdGl0bGUsIGpvYiBjYXRlZ29yeSwgc2FsYXJ5IGluIHZhcmlvdXMgY3VycmVuY2llcywgZW1wbG95ZWUgcmVzaWRlbmNlLCBleHBlcmllbmNlIGxldmVsLCBlbXBsb3ltZW50IHR5cGUsIHdvcmsgc2V0dGluZywgY29tcGFueSBsb2NhdGlvbiwgYW5kIGNvbXBhbnkgc2l6ZS4gVGhpcyByaWNoIGRhdGFzZXQgb2ZmZXJzIGFuIGludmFsdWFibGUgcmVzb3VyY2UgZm9yIGFuYWx5emluZyBzYWxhcnkgdHJlbmRzLCBjb21wYXJpbmcgc2FsYXJpZXMgYWNyb3NzIHJvbGVzIGFuZCByZWdpb25zLCBhbmQgdW5kZXJzdGFuZGluZyB0aGUgZmFjdG9ycyBpbmZsdWVuY2luZyBzYWxhcnkgc3RydWN0dXJlcyB3aXRoaW4gdGhlIGRhdGEgaW5kdXN0cnkuCgpJbiB0aGUgc3Vic2VxdWVudCBzZWN0aW9ucyBvZiB0aGlzIHJlcG9ydCwgd2UgZGVsdmUgZGVlcGVyIGludG8gZWFjaCByZXNlYXJjaCBxdWVzdGlvbiwgcHJlc2VudGluZyBvdXIgZmluZGluZ3MgYW5kIGludGVycHJldGF0aW9ucyBkZXJpdmVkIGZyb20gdGhlIGFuYWx5c2lzIG9mIHRoZSBkYXRhc2V0LiBUaHJvdWdoIHRoaXMgZXhwbG9yYXRpb24sIHdlIGFpbSB0byBwcm92aWRlIGFjdGlvbmFibGUgaW5zaWdodHMgdGhhdCBjYW4gaW5mb3JtIHN0cmF0ZWdpYyBkZWNpc2lvbnMgZm9yIGJvdGggaW5kaXZpZHVhbHMgYW5kIG9yZ2FuaXphdGlvbnMgb3BlcmF0aW5nIHdpdGhpbiB0aGUgZHluYW1pYyBsYW5kc2NhcGUgb2YgZGF0YSBzY2llbmNlLgoKIyBNZXRob2RvbG9neQoKYGBge3J9CiMgaW1wb3J0IHRoZSBkYXRhc2V0CmpvYnNfaW5fZGF0YSA8LSByZWFkLmNzdigifi9Eb3dubG9hZHMvZ2l0aHViL3NhbGFyeXRyZW5kX2RhdGFzY2llbmNlL2pvYnNfaW5fZGF0YS5jc3YiKQojIGZpbHRlciB0byBpbmNsdWRlIDI1IHJhbmRvbSBjb3VudHJpZXMgb3V0IG9mIDgzCnNldC5zZWVkKDEyMykKc2VsZWN0ZWRfZGF0YSA8LSBqb2JzX2luX2RhdGFbLCBjKCJ3b3JrX3llYXIiLCAiam9iX3RpdGxlIiwgInNhbGFyeV9pbl91c2QiLCAiZXhwZXJpZW5jZV9sZXZlbCIsICJlbXBsb3llZV9yZXNpZGVuY2UiKV0KIyBFeHRyYWN0IHVuaXF1ZSBjb3VudHJpZXMgZnJvbSB0aGUgImVtcGxveWVlX3Jlc2lkZW5jZSIgY29sdW1uCnVuaXF1ZV9jb3VudHJpZXMgPC0gdW5pcXVlKHNlbGVjdGVkX2RhdGEkZW1wbG95ZWVfcmVzaWRlbmNlKQoKIyBTZWxlY3QgMTUgcmFuZG9tIHVuaXF1ZSBjb3VudHJpZXMKcmFuZG9tXzE1X2NvdW50cmllcyA8LSBzYW1wbGUodW5pcXVlX2NvdW50cmllcywgMjUpCmZpbHRlcmVkX2RhdGEgPC0gc2VsZWN0ZWRfZGF0YVtzZWxlY3RlZF9kYXRhJGVtcGxveWVlX3Jlc2lkZW5jZSAlaW4lIHJhbmRvbV8xNV9jb3VudHJpZXMsIF0KYGBgCgojIEFuYWx5c2lzCgojIyBTY2F0dGVycGxvdCBvZiBTYWxhcnkgaW4gVVNEIGJ5IEVtcGxveWVlIFJlc2lkZW5jZQoKYGBge3J9CiMgQ3JlYXRlIHRoZSBnZ3Bsb3Qgb2JqZWN0CnNjYXR0ZXJwbG90IDwtIGdncGxvdChmaWx0ZXJlZF9kYXRhLCBhZXMoeCA9IGVtcGxveWVlX3Jlc2lkZW5jZSwgeSA9IHNhbGFyeV9pbl91c2QsIGNvbG9yID0gZW1wbG95ZWVfcmVzaWRlbmNlKSkgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjUpICsgCiAgbGFicyh0aXRsZSA9ICJTY2F0dGVycGxvdCBvZiBTYWxhcnkgaW4gVVNEIGJ5IEVtcGxveWVlIFJlc2lkZW5jZSIsCiAgICAgICB4ID0gIkVtcGxveWVlIFJlc2lkZW5jZSIsCiAgICAgICB5ID0gIlNhbGFyeSBpbiBVU0QiKSArIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OmNvbW1hX2Zvcm1hdCgpKSArIAogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIHZqdXN0ID0gMC41LCBoanVzdCA9IDEpKQoKIyBDb252ZXJ0IGdncGxvdCBvYmplY3QgdG8gYSBwbG90bHkgb2JqZWN0CmludGVyYWN0aXZlX3NjYXR0ZXJwbG90IDwtIGdncGxvdGx5KHNjYXR0ZXJwbG90KQppbnRlcmFjdGl2ZV9zY2F0dGVycGxvdAoKYGBgCgpUaGUgc2NhdHRlcnBsb3QgcHJvdmlkZXMgYSB2aXN1YWwgcmVwcmVzZW50YXRpb24gb2YgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHNhbGFyeSBhbmQgZW1wbG95ZWUgcmVzaWRlbmNlLCBhbGxvd2luZyBmb3IgaW5zaWdodHMgaW50byBzYWxhcnkgZGlzdHJpYnV0aW9uLCByZWdpb25hbCBkaXNwYXJpdGllcywgYW5kIHBvdGVudGlhbCBjb3JyZWxhdGlvbnMuIFRoZSBzYWxhcmllcyB2YXJ5IHNpZ25pZmljYW50bHkgYWNyb3NzIGRpZmZlcmVudCBlbXBsb3llZSByZXNpZGVuY2VzLCByYW5naW5nIGZyb20gYXMgbG93IGFzICQxNSwwMDAgdG8gYXMgaGlnaCBhcyAkMzIzLDkwNS4gQ2VydGFpbiBjb3VudHJpZXMgb3IgcmVnaW9ucyBzZWVtIHRvIGhhdmUgaGlnaGVyIHNhbGFyeSByYW5nZXMgY29tcGFyZWQgdG8gb3RoZXJzLiBGb3IgZXhhbXBsZSwgY291bnRyaWVzIGxpa2UgRnJhbmNlLCBQb3J0dWdhbCwgYW5kIExpdGh1YW5pYSBoYXZlIGEgd2lkZSByYW5nZSBvZiBzYWxhcnkgbGV2ZWxzLCBpbmNsdWRpbmcgYm90aCBoaWdoIGFuZCBtb2RlcmF0ZSBzYWxhcmllcy4gVGhlcmUgYXJlIHNvbWUgaW5zdGFuY2VzIG9mIGV4Y2VwdGlvbmFsbHkgaGlnaCBzYWxhcmllcywgc3VjaCBhcyBpbiBGcmFuY2Ugd2hlcmUgdGhlIHNhbGFyeSByZWFjaGVzICQzMjMsOTA1LCBhbmQgaW4gTmV3IFplYWxhbmQgd2l0aCBhIHNhbGFyeSBvZiAkMTI1LDAwMC4gU2V2ZXJhbCBmYWN0b3JzIGNvdWxkIGNvbnRyaWJ1dGUgdG8gdGhlc2Ugc2FsYXJ5IGRpZmZlcmVuY2VzLCBpbmNsdWRpbmcgbG9jYWwgZWNvbm9taWMgY29uZGl0aW9ucywgY29zdCBvZiBsaXZpbmcsIGRlbWFuZCBmb3Igc3BlY2lmaWMgc2tpbGxzLCBhbmQgaW5kdXN0cnkgc3BlY2lhbGl6YXRpb24gaW4gY2VydGFpbiByZWdpb25zLgoKCiMjIFByZXZhbGVuY2Ugb2YgSm9iIFRpdGxlcyBBY3Jvc3MgUmVnaW9ucwoKYGBge3J9CiMgQ3JlYXRlIGEgc3RhY2tlZCBiYXIgcGxvdAppbnRlcmFjdGl2ZV9zdGFja2VkX2JhciA8LSBmaWx0ZXJlZF9kYXRhICU+JQogIGdyb3VwX2J5KGVtcGxveWVlX3Jlc2lkZW5jZSwgam9iX3RpdGxlKSAlPiUKICBzdW1tYXJpc2UoY291bnQgPSBuKCkpICU+JQogIGdncGxvdChhZXMoeCA9IGVtcGxveWVlX3Jlc2lkZW5jZSwgeSA9IGNvdW50LCBmaWxsID0gam9iX3RpdGxlKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgbGFicyh0aXRsZSA9ICJQcmV2YWxlbmNlIG9mIEpvYiBUaXRsZXMgQWNyb3NzIFJlZ2lvbnMiLAogICAgICAgeCA9ICJSZWdpb24gb3IgQ291bnRyeSIsCiAgICAgICB5ID0gIkNvdW50IiwKICAgICAgIGZpbGwgPSAiSm9iIFRpdGxlIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgCgojIENvbnZlcnQgdGhlIGdncGxvdCBvYmplY3QgdG8gYW4gaW50ZXJhY3RpdmUgcGxvdAppbnRlcmFjdGl2ZV9zdGFja2VkX2JhciA8LSBnZ3Bsb3RseShpbnRlcmFjdGl2ZV9zdGFja2VkX2JhcikKaW50ZXJhY3RpdmVfc3RhY2tlZF9iYXIKCmBgYAoKYEZyYW5jZWA6IExlYWRzIHdpdGggYSB0b3RhbCBjb3VudCBvZiA2OSwgZW5jb21wYXNzaW5nIGEgd2lkZSByYW5nZSBvZiBqb2IgdGl0bGVzIGluY2x1ZGluZyBkYXRhIGVuZ2luZWVyaW5nLCBkYXRhIHNjaWVuY2UsIGFuZCBtYWNoaW5lIGxlYXJuaW5nIGVuZ2luZWVyaW5nLgpgUG9ydHVnYWxgOiBGb2xsb3dzIGNsb3NlbHkgd2l0aCBhIHRvdGFsIGNvdW50IG9mIDI3LCB3aXRoIGRpdmVyc2Ugcm9sZXMgaW4gZGF0YSBhbmFseXNpcywgZGF0YSBlbmdpbmVlcmluZywgYW5kIG1hY2hpbmUgbGVhcm5pbmcgZW5naW5lZXJpbmcuCmBQYWtpc3RhbmA6IFNob3dzIGEgc21hbGxlciBwcmVzZW5jZSB3aXRoIGEgdG90YWwgY291bnQgb2YgNiwgbWFpbmx5IGluIGRhdGEgZW5naW5lZXJpbmcsIGRhdGEgc2NpZW5jZSBjb25zdWx0YW5jeSwgYW5kIEFJIHByb2dyYW1taW5nLgpgUGhpbGlwcGluZXNgOiBFeGhpYml0cyBhIGxpbWl0ZWQgcHJlc2VuY2Ugd2l0aCBhIHRvdGFsIGNvdW50IG9mIDQsIGZvY3VzaW5nIG9uIHJvbGVzIHN1Y2ggYXMgYnVzaW5lc3MgZGF0YSBhbmFseXNpcywgZGF0YSBzY2llbmNlIG1hbmFnZW1lbnQsIGFuZCBkYXRhIGFuYWx5dGljcy4KYEJlbGdpdW0sIExpdGh1YW5pYSwgYW5kIFR1cmtleWA6IEVhY2ggaGF2ZSBhIG1vZGVyYXRlIHByZXNlbmNlIHdpdGggY291bnRzIHJhbmdpbmcgZnJvbSAyIHRvIDQsIHByaW1hcmlseSBpbiByb2xlcyBsaWtlIGRhdGEgc2NpZW50aXN0LCBtYWNoaW5lIGxlYXJuaW5nIGVuZ2luZWVyLCBhbmQgQUkgc2NpZW50aXN0LgpgT3RoZXIgY291bnRyaWVzYDogSGF2ZSBtaW5pbWFsIHJlcHJlc2VudGF0aW9uLCB3aXRoIGNvdW50cyByYW5naW5nIGZyb20gMSB0byAyLCBlbmNvbXBhc3Npbmcgc3BlY2lmaWMgam9iIHRpdGxlcy4KCiMjIERpc3RyaWJ1dGlvbiBvZiBFeHBlcmllbmNlIExldmVscwoKYGBge3J9CiMgQ3JlYXRlIGFuIGludGVyYWN0aXZlIGJhcnBsb3QgdXNpbmcgcGxvdF9seSAKaW50ZXJhY3RpdmVfYmFycGxvdCA8LSBwbG90X2x5KGRhdGEgPSBmaWx0ZXJlZF9kYXRhLCB4ID0gfmV4cGVyaWVuY2VfbGV2ZWwsIHR5cGUgPSAiaGlzdG9ncmFtIiwgbWFya2VyID0gbGlzdChjb2xvciA9ICJicm93biIpKSAlPiUKICBsYXlvdXQodGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIEV4cGVyaWVuY2UgTGV2ZWxzIiwKICAgICAgICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gIkV4cGVyaWVuY2UgTGV2ZWwiKSwKICAgICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gIkZyZXF1ZW5jeSIpKQoKIyBkaXNwbGF5IHRoZSBpbnRlcmFjdGl2ZSBiYXJwbG90CmludGVyYWN0aXZlX2JhcnBsb3QKCmBgYAoKVGhlIGRpc3RyaWJ1dGlvbiBvZiBleHBlcmllbmNlIGxldmVscyBhbW9uZyBlbXBsb3llZXMgaW4gdGhlIGZpbHRlcmVkIGRhdGFzZXQgZm9yIDI1IGNvdW50cmllcyBpcyBhcyBmb2xsb3dzOiB0aGVyZSBhcmUgMzUgZW50cnktbGV2ZWwsIDMgZXhlY3V0aXZlLCA1MSBtaWQtbGV2ZWwsIGFuZCA0MyBzZW5pb3ItbGV2ZWwgcG9zaXRpb25zLiBUaGlzIGRpc3RyaWJ1dGlvbiBwcm92aWRlcyBpbnNpZ2h0IGludG8gdGhlIHdvcmtmb3JjZSBjb21wb3NpdGlvbiBhbmQgaGlnaGxpZ2h0cyB0aGUgcHJldmFsZW5jZSBvZiBtaWQtbGV2ZWwgYW5kIHNlbmlvci1sZXZlbCByb2xlcyBjb21wYXJlZCB0byBlbnRyeS1sZXZlbCBhbmQgZXhlY3V0aXZlIHBvc2l0aW9ucy4gVW5kZXJzdGFuZGluZyB0aGlzIGRpc3RyaWJ1dGlvbiBjYW4gYWlkIGluIHdvcmtmb3JjZSBwbGFubmluZywgdGFsZW50IG1hbmFnZW1lbnQsIGFuZCBvcmdhbml6YXRpb25hbCBkZXZlbG9wbWVudCBzdHJhdGVnaWVzLgoKIyMgQXZlcmFnZSBTYWxhcnkgT3ZlciBZZWFycwoKYGBge3J9CiMgQXZlcmFnZSBzYWxhcnkgb3ZlciB5ZWFycwphdmVyYWdlX3NhbGFyeSA8LSBmaWx0ZXJlZF9kYXRhICU+JSAKICBncm91cF9ieSh3b3JrX3llYXIpICU+JSAKICBzdW1tYXJpc2UoYXZnX3NhbGFyeSA9IG1lYW4oc2FsYXJ5X2luX3VzZCkpCgojIENyZWF0ZSBhbiBpbnRlcmFjdGl2ZSBsaW5lIHBsb3QgZm9yIGF2ZXJhZ2Ugc2FsYXJ5IG92ZXIgeWVhcnMKaW50ZXJhY3RpdmVfbGluZV9wbG90IDwtIHBsb3RfbHkoZGF0YSA9IGF2ZXJhZ2Vfc2FsYXJ5LCB4ID0gfndvcmtfeWVhciwgeSA9IH5hdmdfc2FsYXJ5LCB0eXBlID0gInNjYXR0ZXIiLCBtb2RlID0gImxpbmVzK21hcmtlcnMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5lID0gbGlzdChjb2xvciA9ICJibGFjayIpKSAlPiUKICBsYXlvdXQodGl0bGUgPSAiQXZlcmFnZSBTYWxhcnkgT3ZlciBZZWFycyIsCiAgICAgICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICJZZWFyIiksCiAgICAgICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICJBdmVyYWdlIFNhbGFyeSAoVVNEKSIpKQoKIyBkaXNwbGF5IHRoZSBpbnRlcmFjdGl2ZSBsaW5lIHBsb3QKaW50ZXJhY3RpdmVfbGluZV9wbG90CgpgYGAKVGhlIGdyYXBoIHJldmVhbHMgYSBub3RhYmxlIGluY3JlYXNlIGluIHRoZSBhdmVyYWdlIHNhbGFyeSBvdmVyIHRoZSB5ZWFycywgcmVmbGVjdGluZyBwb3RlbnRpYWwgdHJlbmRzIGluIHRoZSBqb2IgbWFya2V0IG9yIGVjb25vbWljIGNvbmRpdGlvbnMuIEluIDIwMjAsIHRoZSBhdmVyYWdlIHNhbGFyeSB3YXMgJDU5LjA0aywgc2hvd2luZyBhIHNsaWdodCBkZWNyZXNlIHRvICQ1Ny40M2sgaW4gMjAyMS4gSG93ZXZlciwgYSBtb3JlIHNpZ25pZmljYW50IGp1bXAgb2NjdXJyZWQgaW4gMjAyMiwgd2l0aCB0aGUgYXZlcmFnZSBzYWxhcnkgcmlzaW5nIHRvICQ2NS41NmsuIFRoaXMgaW5jcmVhc2UgY291bGQgc2lnbmlmeSBmYWN0b3JzIHN1Y2ggYXMgaW5kdXN0cnkgZ3Jvd3RoLCBkZW1hbmQgZm9yIHNraWxsZWQgcHJvZmVzc2lvbmFscywgb3IgaW5mbGF0aW9uYXJ5IHByZXNzdXJlcyBpbXBhY3RpbmcgY29tcGVuc2F0aW9uLiBUaGUgbW9zdCBzdWJzdGFudGlhbCBpbmNyZWFzZSBpcyBvYnNlcnZlZCBpbiAyMDIzLCB3aGVyZSB0aGUgYXZlcmFnZSBzYWxhcnkgc3VyZ2VkIHRvICQ4MS4wOWssIHN1Z2dlc3Rpbmcgcm9idXN0IGVjb25vbWljIGNvbmRpdGlvbnMsIGhpZ2ggZGVtYW5kIGZvciB0YWxlbnQsIG9yIGFkdmFuY2VtZW50cyBpbiBzcGVjaWFsaXplZCBza2lsbHMgZHJpdmluZyB1cCBjb21wZW5zYXRpb24gbGV2ZWxzLiBPdmVyYWxsLCB0aGlzIGFuYWx5c2lzIGhpZ2hsaWdodHMgdGhlIGR5bmFtaWMgbmF0dXJlIG9mIHNhbGFyeSB0cmVuZHMgYW5kIHVuZGVyc2NvcmVzIHRoZSBpbXBvcnRhbmNlIG9mIG1vbml0b3JpbmcgYW5kIGFkYXB0aW5nIHRvIGNoYW5naW5nIG1hcmtldCBjb25kaXRpb25zIGZvciBib3RoIGVtcGxveWVycyBhbmQgZW1wbG95ZWVzLgoKIyMgU2FsYXJ5IERpc3RyaWJ1dGlvbiBieSBKb2IgVGl0bGUKCmBgYHtyfQojIENyZWF0ZSBpbnRlcmFjdGl2ZSBib3hwbG90IGZvciBzYWxhcnkgZGlzdHJpYnV0aW9uIGFjY29yZGluZyB0byBqb2IgdGl0bGUKaW50ZXJhY3RpdmVfc2FsYXJ5X2JveHBsb3QgPC0gcGxvdF9seShmaWx0ZXJlZF9kYXRhLCB4ID0gfmpvYl90aXRsZSwgeSA9IH5zYWxhcnlfaW5fdXNkLCB0eXBlID0gImJveCIpICU+JQogIGxheW91dCh0aXRsZSA9ICJTYWxhcnkgRGlzdHJpYnV0aW9uIGJ5IEpvYiBUaXRsZSIsCiAgICAgICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICJKb2IgVGl0bGUiKSwKICAgICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gIlNhbGFyeSAoVVNEKSIpKQoKIyBQcmludCB0aGUgaW50ZXJhY3RpdmUgYm94cGxvdAppbnRlcmFjdGl2ZV9zYWxhcnlfYm94cGxvdApgYGAKClRoZSBpbnRlcmFjdGl2ZSBib3hwbG90IGFuYWx5c2lzIHByb3ZpZGVzIHZhbHVhYmxlIGluc2lnaHRzIGludG8gdGhlIHNhbGFyeSBkaXN0cmlidXRpb24gYWNyb3NzIGRpZmZlcmVudCBqb2IgdGl0bGVzLiBBbW9uZyB0aGUgam9iIHRpdGxlcyBleGFtaW5lZCwgIkhlYWQgb2YgRGF0YSwiICJSZXNlYXJjaCBFbmdpbmVlciwiIGFuZCAiQUkgRGV2ZWxvcGVyIiBzdGFuZCBvdXQgZm9yIHRoZWlyIG5vdGFibGUgdmFyaWF0aW9uIGluIHNhbGFyeS4gVGhlIGJveHBsb3QgaWxsdXN0cmF0ZXMgY29uc2lkZXJhYmxlIHZhcmlhYmlsaXR5IGluIHNhbGFyaWVzIHdpdGhpbiB0aGUgcm9sZXMsIHdpdGggc29tZSBpbmRpdmlkdWFscyBwb3RlbnRpYWxseSBlYXJuaW5nIHN1YnN0YW50aWFsbHkgaGlnaGVyIG9yIGxvd2VyIHRoYW4gdGhlIG1lZGlhbi4gVGhpcyB2YXJpYXRpb24gY291bGQgYmUgYXR0cmlidXRlZCB0byBmYWN0b3JzIHN1Y2ggYXMgeWVhcnMgb2YgZXhwZXJpZW5jZSwgaW5kdXN0cnkgc3BlY2lhbGl6YXRpb24sIG9yIGFkZGl0aW9uYWwgcXVhbGlmaWNhdGlvbnMuCgpIZWFkIG9mIERhdGE6IFRoZSBtZWRpYW4gc2FsYXJ5IGZvciB0aGlzIHBvc2l0aW9uIGlzICQxMzcsMDAwLCBpbmRpY2F0aW5nIGEgc2lnbmlmaWNhbnQgZWFybmluZyBwb3RlbnRpYWwuIAoKUmVzZWFyY2ggRW5naW5lZXI6IFdpdGggYSBtZWRpYW4gc2FsYXJ5IG9mICQxNjgsMDAwLCB0aGUgcm9sZSBvZiBhIFJlc2VhcmNoIEVuZ2luZWVyIGNvbW1hbmRzIGNvbnNpZGVyYWJsZSBjb21wZW5zYXRpb24uIAoKQUkgRGV2ZWxvcGVyOiBUaGUgbWVkaWFuIHNhbGFyeSBmb3IgQUkgRGV2ZWxvcGVycyBpcyAkMTE4LDAwMCwgcmVmbGVjdGluZyB0aGUgZGVtYW5kIGZvciBwcm9mZXNzaW9uYWxzIHNraWxsZWQgaW4gYXJ0aWZpY2lhbCBpbnRlbGxpZ2VuY2UgdGVjaG5vbG9naWVzLgoKIyMgU2FsYXJ5IERpc3RyaWJ1dGlvbiBieSBFeHBlcmllbmNlIExldmVsCgpgYGB7cn0KIyBzYWxhcnkgZGlzdHJpYnV0aW9uIGFjY29yZGluZyB0byBleHBlcmllbmNlIGxldmVsCiMgQ3JlYXRlIGludGVyYWN0aXZlIGJveHBsb3QgZm9yIHNhbGFyeSBkaXN0cmlidXRpb24gYWNjb3JkaW5nIHRvIGV4cGVyaWVuY2UgbGV2ZWwKaW50ZXJhY3RpdmVfZXhwX2JveHBsb3QgPC0gcGxvdF9seShmaWx0ZXJlZF9kYXRhLCB4ID0gfmV4cGVyaWVuY2VfbGV2ZWwsIHkgPSB+c2FsYXJ5X2luX3VzZCwgdHlwZSA9ICJib3giKSAlPiUKICBsYXlvdXQodGl0bGUgPSAiU2FsYXJ5IERpc3RyaWJ1dGlvbiBieSBFeHBlcmllbmNlIExldmVsIiwKICAgICAgICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gIkV4cGVyaWVuY2UgTGV2ZWwiKSwKICAgICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gIlNhbGFyeSAoVVNEKSIpKQoKIyBQcmludCB0aGUgaW50ZXJhY3RpdmUgYm94cGxvdAppbnRlcmFjdGl2ZV9leHBfYm94cGxvdApgYGAKClRoZSBzYWxhcnkgZGlzdHJpYnV0aW9uIGFuYWx5c2lzIGJ5IGV4cGVyaWVuY2UgbGV2ZWwgcmV2ZWFscyBkaXN0aW5jdCB0cmVuZHM6CgotIEVudHJ5IExldmVsOiBNZWRpYW4gc2FsYXJ5IGlzICQ0MCwwMDAsIHR5cGljYWwgZm9yIG5ldyBvciBsZXNzIGV4cGVyaWVuY2VkIHdvcmtlcnMuICBUaGlzIHNhbGFyeSBsZXZlbCByZWZsZWN0cyB0aGUgY29tcGVuc2F0aW9uIHR5cGljYWxseSBvZmZlcmVkIHRvIGluZGl2aWR1YWxzIHdobyBhcmUgbmV3IHRvIHRoZSB3b3JrZm9yY2Ugb3IgaGF2ZSBsaW1pdGVkIHByb2Zlc3Npb25hbCBleHBlcmllbmNlLiBFbnRyeS1sZXZlbCBzYWxhcmllcyBtYXkgdmFyeSBkZXBlbmRpbmcgb24gZmFjdG9ycyBzdWNoIGFzIGluZHVzdHJ5LCBsb2NhdGlvbiwgYW5kIHNwZWNpZmljIGpvYiByb2xlcy4KCi0gRXhlY3V0aXZlOiBNZWRpYW4gc2FsYXJ5IGp1bXBzIHRvICQxMDYsMDAwLCByZWZsZWN0aW5nIHRoZSBoaWdoIHJlc3BvbnNpYmlsaXRpZXMgb2YgbGVhZGVyc2hpcCByb2xlcy4gRXhlY3V0aXZlcyB0eXBpY2FsbHkgaG9sZCB0b3AgbGVhZGVyc2hpcCBwb3NpdGlvbnMgd2l0aGluIG9yZ2FuaXphdGlvbnMgYW5kIGFyZSByZXNwb25zaWJsZSBmb3Igc3RyYXRlZ2ljIGRlY2lzaW9uLW1ha2luZyBhbmQgb3ZlcnNlZWluZyBjb21wYW55IG9wZXJhdGlvbnMuIFRoZSBoaWdoZXIgc2FsYXJ5IHJhbmdlIGZvciBleGVjdXRpdmVzIHJlZmxlY3RzIHRoZSBzaWduaWZpY2FudCByZXNwb25zaWJpbGl0aWVzIGFuZCBsZWFkZXJzaGlwIHJvbGVzIHRoZXkgdW5kZXJ0YWtlLgoKLSBNaWQgTGV2ZWw6IE1lZGlhbiBzYWxhcnkgc3RhbmRzIGF0ICQ1NywyMjAsIGluZGljYXRpbmcgbW9kZXJhdGUgZXhwZXJpZW5jZSBhbmQgcmVzcG9uc2liaWxpdGllcy4gTWlkLWxldmVsIHBvc2l0aW9ucyBvZnRlbiByZXF1aXJlIGEgbW9kZXJhdGUgbGV2ZWwgb2YgZXhwZXJpZW5jZSBhbmQgZXhwZXJ0aXNlLCB3aXRoIGluZGl2aWR1YWxzIGFzc3VtaW5nIHJvbGVzIHRoYXQgaW52b2x2ZSBncmVhdGVyIHJlc3BvbnNpYmlsaXRpZXMgYW5kIHNwZWNpYWxpemVkIHNraWxscyBjb21wYXJlZCB0byBlbnRyeS1sZXZlbCBwb3NpdGlvbnMuIFRoZSBzYWxhcnkgcmVmbGVjdHMgYSBtaWRwb2ludCBiZXR3ZWVuIGVudHJ5LWxldmVsIGFuZCBzZW5pb3ItbGV2ZWwgY29tcGVuc2F0aW9uLgoKLSBTZW5pb3IgTGV2ZWw6IE1lZGlhbiBzYWxhcnkgcmlzZXMgdG8gJDc2LDA1MCwgcmVmbGVjdGluZyBleHRlbnNpdmUgZXhwZXJpZW5jZSBhbmQgbGVhZGVyc2hpcCByb2xlcy4gU2VuaW9yLWxldmVsIHJvbGVzIHR5cGljYWxseSByZXF1aXJlIGV4dGVuc2l2ZSBleHBlcmllbmNlLCBzcGVjaWFsaXplZCBza2lsbHMsIGFuZCBhIHRyYWNrIHJlY29yZCBvZiBsZWFkZXJzaGlwIGFuZCBhY2NvbXBsaXNobWVudHMuIFRoZSBoaWdoZXIgY29tcGVuc2F0aW9uIHJlZmxlY3RzIHRoZSB2YWx1ZSBwbGFjZWQgb24gdGhlIGV4cGVydGlzZSBhbmQgY29udHJpYnV0aW9ucyBvZiBzZW5pb3IgcHJvZmVzc2lvbmFscyB0byBvcmdhbml6YXRpb25zLgoKT3ZlcmFsbCwgc2FsYXJpZXMgaW5jcmVhc2Ugc2lnbmlmaWNhbnRseSBhcyBwcm9mZXNzaW9uYWxzIHByb2dyZXNzIGZyb20gZW50cnkgdG8gc2VuaW9yIGxldmVscywgcmVmbGVjdGluZyB0aGVpciBleHBlcmllbmNlIGFuZCBjb250cmlidXRpb25zIHRvIG9yZ2FuaXphdGlvbnMuCgojIyBUcmVlbWFwIG9mIEF2ZXJhZ2UgU2FsYXJ5IGJ5IEVtcGxveWVlIFJlc2lkZW5jZSBhbmQgSm9iIFRpdGxlCgpgYGB7cn0KIyBHZW9ncmFwaGljYWwgc2FsYXJ5IGRpc3RyaWJ1dGlvbgojIEdyb3VwIHRoZSBkYXRhCmdyb3VwZWRfZGF0YSA8LSBmaWx0ZXJlZF9kYXRhICU+JQogIGdyb3VwX2J5KGVtcGxveWVlX3Jlc2lkZW5jZSwgam9iX3RpdGxlLCBzYWxhcnlfaW5fdXNkKSAlPiUKICBzdW1tYXJpc2UoY291bnQgPSBuKCkpCgojIENhbGN1bGF0ZSBhdmVyYWdlIHNhbGFyeSBwZXIgZ3JvdXAKYXZlcmFnZV9zYWxhcnkgPC0gZ3JvdXBlZF9kYXRhICU+JQogIGdyb3VwX2J5KGpvYl90aXRsZSwgZW1wbG95ZWVfcmVzaWRlbmNlKSAlPiUKICBzdW1tYXJpc2UoYXZnX3NhbGFyeSA9IG1lYW4oc2FsYXJ5X2luX3VzZCksIC5ncm91cHMgPSAnZHJvcCcpCgojIENyZWF0ZSB0aGUgdHJlZW1hcApkYXRhX3NjaWVuY2VfdHJlZW1hcCA8LSB0cmVlbWFwKGF2ZXJhZ2Vfc2FsYXJ5LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCA9IGMoImpvYl90aXRsZSIsICJlbXBsb3llZV9yZXNpZGVuY2UiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdlNpemUgPSAiYXZnX3NhbGFyeSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlID0gIlRyZWVtYXAgb2YgQXZlcmFnZSBTYWxhcnkgYnkgRW1wbG95ZWUgUmVzaWRlbmNlIGFuZCBKb2IgVGl0bGUiKQoKIyBQcmludCB0aGUgdHJlZW1hcAojIHByaW50KGRhdGFfc2NpZW5jZV90cmVlbWFwKQpkM3RyZWUoZGF0YV9zY2llbmNlX3RyZWVtYXAsIHJvb3RuYW1lID0gIkpvYnMiKQoKYGBgCkluIHRoaXMgYW5hbHlzaXMsIHdlIGdlbmVyYXRlZCBhIHRyZWVtYXAgZ3JhcGggYWxvbmcgd2l0aCBpdHMgaW50ZXJhY3RpdmUgdmVyc2lvbiwgc2hvd2Nhc2luZyB0aGUgYXZlcmFnZSBzYWxhcnkgZGlzdHJpYnV0aW9uIGFjY29yZGluZyB0byBlbXBsb3llZSByZXNpZGVuY2UgYW5kIGpvYiB0aXRsZXMuIFRoZSB0cmVlbWFwIHZpc3VhbGl6YXRpb24gYWxsb3dlZCB1cyB0byBleHBsb3JlIHRoZSBzYWxhcnkgdHJlbmRzIGFjcm9zcyBkaWZmZXJlbnQgY291bnRyaWVzIGFuZCBqb2Igcm9sZXMgZWZmaWNpZW50bHkuCgpVcG9uIGV4YW1pbmF0aW9uIG9mIHRoZSBncmFwaCwgaXQgd2FzIGV2aWRlbnQgdGhhdCBjZXJ0YWluIGpvYiB0aXRsZXMgY29tbWFuZGVkIGhpZ2hlciBhdmVyYWdlIHNhbGFyaWVzIGFjcm9zcyB2YXJpb3VzIGNvdW50cmllcy4gU3BlY2lmaWNhbGx5LCByb2xlcyBzdWNoIGFzIE1MIGVuZ2luZWVyLCBkYXRhIGVuZ2luZWVyLCBkYXRhIHNjaWVudGlzdCwgZmluYW5jZSBkYXRhIGFuYWx5c3QsIGRhdGEgYW5hbHlzdCwgYW5kIGhlYWQgb2YgZGF0YSBjb25zaXN0ZW50bHkgZW1lcmdlZCB3aXRoIHRoZSBoaWdoZXN0IGF2ZXJhZ2Ugc2FsYXJpZXMuCgojIyBTYWxhcnkgVHJlbmQgZm9yIERhdGEgU2NpZW50aXN0cyBPdmVyIFdvcmsgWWVhcnMKCmBgYHtyfQojIHNhbGFyeSBvZiBvdmVyIHllYXJzCiMgRmlsdGVyIHRoZSBkYXRhIGZvciBEYXRhIFNjaWVudGlzdHMKZGF0YV9zY2llbnRpc3Rfc2FsYXJ5IDwtIGZpbHRlcmVkX2RhdGFbZmlsdGVyZWRfZGF0YSRqb2JfdGl0bGUgPT0gIkRhdGEgU2NpZW50aXN0IiwgXQoKIyBDcmVhdGUgdGhlIHNjYXR0ZXIgcGxvdApzY2F0dGVyX3Bsb3QgPC0gZ2dwbG90KGRhdGFfc2NpZW50aXN0X3NhbGFyeSwgYWVzKHggPSB3b3JrX3llYXIsIHkgPSBzYWxhcnlfaW5fdXNkKSkgKwogIGdlb21fcG9pbnQoY29sb3IgPSAiYmx1ZSIsIGFscGhhID0gMC41KSArCiAgbGFicyh0aXRsZSA9ICJTYWxhcnkgVHJlbmQgZm9yIERhdGEgU2NpZW50aXN0cyBPdmVyIFdvcmsgWWVhcnMiLAogICAgICAgeCA9ICJXb3JrIFllYXIiLAogICAgICAgeSA9ICJTYWxhcnkgKFVTRCkiKQoKIyBBZGQgdHJlbmQgbGluZQpzY2F0dGVyX3Bsb3Rfd2l0aF90cmVuZCA8LSBzY2F0dGVyX3Bsb3QgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UsIGNvbG9yID0gImJsYWNrIiwgbGluZXdpZHRoID0gMC41KQoKIyBDb252ZXJ0IHRvIHBsb3RseSBvYmplY3QKaW50ZXJhY3RpdmVfcGxvdCA8LSBnZ3Bsb3RseShzY2F0dGVyX3Bsb3Rfd2l0aF90cmVuZCkKCiMgUHJpbnQgdGhlIGludGVyYWN0aXZlIHBsb3QKaW50ZXJhY3RpdmVfcGxvdAoKCiMgVE8gQ0hFQ0sgSUYgVEhFIFRSRU5EIExJTkUgSVMgSU5DUkVBU0lORy9ERUNSRUFTSU5HCiMgRml0IGEgbGluZWFyIG1vZGVsIHRvIHRoZSBkYXRhCmxtX21vZGVsIDwtIGxtKHNhbGFyeV9pbl91c2QgfiB3b3JrX3llYXIsIGRhdGEgPSBkYXRhX3NjaWVudGlzdF9zYWxhcnkpCgojIEdldCB0aGUgY29lZmZpY2llbnRzIG9mIHRoZSBsaW5lYXIgbW9kZWwgYW5kIHNsb3AKY29lZmZpY2llbnRzIDwtIGNvZWYobG1fbW9kZWwpCnNsb3BlIDwtIGNvZWZmaWNpZW50c1syXQoKIyBDaGVjayBpZiB0aGUgc2xvcGUgaXMgcG9zaXRpdmUsIGluZGljYXRpbmcgYW4gaW5jcmVhc2Ugb3ZlciB5ZWFycwppZiAoc2xvcGUgPiAwKSB7CiAgY2F0KCJUaGUgdHJlbmQgbGluZSBpbmRpY2F0ZXMgYW4gaW5jcmVhc2UgaW4gc2FsYXJpZXMgb3ZlciB0aGUgeWVhcnMuIikKfSBlbHNlIGlmIChzbG9wZSA9PSAwKSB7CiAgY2F0KCJUaGUgdHJlbmQgbGluZSBpbmRpY2F0ZXMgbm8gY2hhbmdlIGluIHNhbGFyaWVzIG92ZXIgdGhlIHllYXJzLiIpCn0gZWxzZSB7CiAgY2F0KCJUaGUgdHJlbmQgbGluZSBpbmRpY2F0ZXMgYSBkZWNyZWFzZSBpbiBzYWxhcmllcyBvdmVyIHRoZSB5ZWFycy4iKQp9CgpgYGAKQmFzZWQgb24gb3VyIGFuYWx5c2lzIGZvY3VzaW5nIG9uIHRoZSBkYXRhIHNjaWVudGlzdCByb2xlLCB3aGljaCBhcHBlYXJzIHRvIGhhdmUgdGhlIGhpZ2hlc3QgcmVwcmVzZW50YXRpb24gYWNyb3NzIHRoZSBzZWxlY3RlZCBjb3VudHJpZXMsIHdlIGludmVzdGlnYXRlZCB0aGUgc2FsYXJ5IHRyZW5kcyBvdmVyIHRoZSB5ZWFycy4gT3VyIGV4YW1pbmF0aW9uLCBhcyBkZXBpY3RlZCBpbiB0aGUgZ3JhcGggYW5kIGNvbmZpcm1lZCBieSB0aGUgbGluZWFyIG1vZGVsIHJlc3VsdHMsIHJldmVhbHMgYSBzdWJ0bGUgYnV0IGRpc2Nlcm5pYmxlIGluY3JlYXNlIGluIHNhbGFyeSBvdmVyIHRoZSB5ZWFycy4gV2hpbGUgdGhlIHVwd2FyZCB0cmFqZWN0b3J5IGlzIGV2aWRlbnQsIGl0J3MgaW1wb3J0YW50IHRvIG5vdGUgdGhhdCB0aGUgcmF0ZSBvZiBpbmNyZWFzZSBhcHBlYXJzIHRvIGJlIG1pbmltYWwuIFRoaXMgb2JzZXJ2YXRpb24gc3VnZ2VzdHMgdGhhdCB3aGlsZSB0aGVyZSBpcyBhIHBvc2l0aXZlIHRyZW5kIGluIGRhdGEgc2NpZW50aXN0IHNhbGFyaWVzIG92ZXIgdGltZSwgdGhlIGdyb3d0aCByYXRlIG1heSBiZSByZWxhdGl2ZWx5IHNsb3cuIFRoaXMgaW5zaWdodCB1bmRlcnNjb3JlcyB0aGUgc3RhYmlsaXR5IG9yIG1vZGVzdCBncm93dGggaW4gY29tcGVuc2F0aW9uIGZvciBkYXRhIHNjaWVudGlzdHMgd2l0aGluIHRoZSBzZWxlY3RlZCByZWdpb25zIG92ZXIgdGhlIHNwZWNpZmllZCBwZXJpb2QuIAoKCiMgUmVzdWx0cwoKSW4gdGhpcyBzdHVkeSwgd2UgYW5hbHl6ZWQgZGF0YSBmcm9tIDI1IHJhbmRvbWx5IHNlbGVjdGVkIGNvdW50cmllcywgZm9jdXNpbmcgb24gZml2ZSBrZXkgdmFyaWFibGVzOiBqb2IgdGl0bGUsIGVtcGxveWVlIHJlc2lkZW5jZSwgc2FsYXJ5IGluIFVTRCwgd29yayBleHBlcmllbmNlLCBhbmQgd29yayB5ZWFyLiBPdXIgYW5hbHlzaXMgY29tcHJpc2VkIHNldmVyYWwgZ3JhcGhpY2FsIHJlcHJlc2VudGF0aW9ucywgZWFjaCBvZmZlcmluZyBpbnNpZ2h0cyBpbnRvIGRpZmZlcmVudCBhc3BlY3RzIG9mIHRoZSBkYXRhc2V0OgoKCkNoYXRHUFQKUmVzdWx0cwoKSW4gdGhpcyBzdHVkeSwgd2UgYW5hbHl6ZWQgZGF0YSBmcm9tIDI1IHJhbmRvbWx5IHNlbGVjdGVkIGNvdW50cmllcywgZm9jdXNpbmcgb24gZml2ZSBrZXkgdmFyaWFibGVzOiBqb2IgdGl0bGUsIGVtcGxveWVlIHJlc2lkZW5jZSwgc2FsYXJ5IGluIFVTRCwgd29yayBleHBlcmllbmNlLCBhbmQgd29yayB5ZWFyLiBPdXIgYW5hbHlzaXMgY29tcHJpc2VkIHNldmVyYWwgZ3JhcGhpY2FsIHJlcHJlc2VudGF0aW9ucywgZWFjaCBvZmZlcmluZyBpbnNpZ2h0cyBpbnRvIGRpZmZlcmVudCBhc3BlY3RzIG9mIHRoZSBkYXRhc2V0OgoKLSBTY2F0dGVycGxvdCBBbmFseXNpczogV2UgY29uZHVjdGVkIGEgc2NhdHRlcnBsb3QgYW5hbHlzaXMgdG8gdmlzdWFsaXplIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBlbXBsb3llZSByZXNpZGVuY2UgYW5kIHNhbGFyeSBpbiBVU0QuCi0gU3RhY2tlZCBCYXJwbG90OiBBIHN0YWNrZWQgYmFycGxvdCB3YXMgdXRpbGl6ZWQgdG8gaWxsdXN0cmF0ZSB0aGUgcHJldmFsZW5jZSBvZiB2YXJpb3VzIGpvYiB0aXRsZXMgYWNyb3NzIGRpZmZlcmVudCBlbXBsb3llZSByZXNpZGVuY2UgY291bnRyaWVzLgotIEJhcnBsb3Qgb2YgRXhwZXJpZW5jZSBMZXZlbHM6IFdlIGNyZWF0ZWQgYSBiYXJwbG90IGRlcGljdGluZyB0aGUgZGlzdHJpYnV0aW9uIG9mIGV4cGVyaWVuY2UgbGV2ZWxzIGFtb25nIHRoZSBzYW1wbGVkIGRhdGEuCi0gQXZlcmFnZSBTYWxhcnkgT3ZlciBZZWFyczogQSBsaW5lcGxvdCBncmFwaCB3YXMgZ2VuZXJhdGVkIHRvIGRpc3BsYXkgdGhlIGF2ZXJhZ2Ugc2FsYXJ5IHRyZW5kcyBvdmVyIHRoZSB5ZWFycy4KLSBTYWxhcnkgRGlzdHJpYnV0aW9uIGJ5IEpvYiBUaXRsZTogV2UgZW1wbG95ZWQgYSBib3hwbG90IHRvIHNob3djYXNlIHRoZSBkaXN0cmlidXRpb24gb2Ygc2FsYXJpZXMgYWNjb3JkaW5nIHRvIGRpZmZlcmVudCBqb2IgdGl0bGVzLgotIFNhbGFyeSBEaXN0cmlidXRpb24gYnkgRXhwZXJpZW5jZSBMZXZlbDogQW5vdGhlciBib3hwbG90IHdhcyB1dGlsaXplZCB0byB2aXN1YWxpemUgdGhlIHNhbGFyeSBkaXN0cmlidXRpb24gYWNyb3NzIHZhcmlvdXMgZXhwZXJpZW5jZSBsZXZlbHMuCi0gVHJlZW1hcCBWaXN1YWxpemF0aW9uOiBBIHRyZWVtYXAgd2FzIGNvbnN0cnVjdGVkIHRvIHByZXNlbnQgdGhlIGF2ZXJhZ2Ugc2FsYXJ5IGRpc3RyaWJ1dGlvbiBieSBlbXBsb3llZSByZXNpZGVuY2UgYW5kIGpvYiB0aXRsZS4KLSBTYWxhcnkgVHJlbmQgQW5hbHlzaXMgZm9yIERhdGEgU2NpZW50aXN0czogRmluYWxseSwgd2UgY29uZHVjdGVkIGEgdHJlbmQgYW5hbHlzaXMgc3BlY2lmaWNhbGx5IGZvY3VzaW5nIG9uIHRoZSBzYWxhcnkgdHJlbmQgZm9yIGRhdGEgc2NpZW50aXN0cyBvdmVyIHRoZSB5ZWFycy4KClRoZXNlIGdyYXBoaWNhbCByZXByZXNlbnRhdGlvbnMgb2ZmZXIgdmFsdWFibGUgaW5zaWdodHMgaW50byB0aGUgZGF0YXNldCwgcHJvdmlkaW5nIGEgY29tcHJlaGVuc2l2ZSB1bmRlcnN0YW5kaW5nIG9mIHNhbGFyeSBkaXN0cmlidXRpb25zLCB0cmVuZHMsIGFuZCB2YXJpYXRpb25zIGFjcm9zcyBkaWZmZXJlbnQgdmFyaWFibGVzIGFuZCBvdmVyIHRpbWUuCgoKIyBDb25jbHVzaW9ucwoKSW4gdGhpcyBjb21wcmVoZW5zaXZlIGFuYWx5c2lzLCB3ZSBkZWx2ZWQgaW50byB2YXJpb3VzIGFzcGVjdHMgb2Ygc2FsYXJ5IGRpc3RyaWJ1dGlvbiwgd29ya2ZvcmNlIGNvbXBvc2l0aW9uLCBhbmQgc2FsYXJ5IHRyZW5kcyBhY3Jvc3MgZGlmZmVyZW50IGpvYiB0aXRsZXMsIGV4cGVyaWVuY2UgbGV2ZWxzLCBhbmQgZ2VvZ3JhcGhpY2FsIHJlZ2lvbnMuIFRocm91Z2ggaW50ZXJhY3RpdmUgdmlzdWFsaXphdGlvbnMgYW5kIHN0YXRpc3RpY2FsIGFuYWx5c2VzLCB3ZSBnYWluZWQgdmFsdWFibGUgaW5zaWdodHMgaW50byB0aGUgZHluYW1pY3Mgb2YgY29tcGVuc2F0aW9uIHdpdGhpbiB0aGUgaW5kdXN0cnkuCgpUaGUgc2NhdHRlcnBsb3QgZGVwaWN0aW5nIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBzYWxhcnkgYW5kIGVtcGxveWVlIHJlc2lkZW5jZSByZXZlYWxlZCBzaWduaWZpY2FudCB2YXJpYXRpb25zIGluIHNhbGFyeSBsZXZlbHMgYWNyb3NzIGRpZmZlcmVudCBjb3VudHJpZXMsIHVuZGVyc2NvcmluZyByZWdpb25hbCBkaXNwYXJpdGllcyBhbmQgcG90ZW50aWFsIGZhY3RvcnMgaW5mbHVlbmNpbmcgY29tcGVuc2F0aW9uLiBGdXJ0aGVybW9yZSwgdGhlIHN0YWNrZWQgYmFycGxvdCBwcm92aWRlZCBhIGNsZWFyIG92ZXJ2aWV3IG9mIHRoZSBwcmV2YWxlbmNlIG9mIGRpZmZlcmVudCBqb2IgdGl0bGVzIGFjcm9zcyB2YXJpb3VzIGVtcGxveWVlIHJlc2lkZW5jZXMsIGhpZ2hsaWdodGluZyBjb3VudHJpZXMgd2l0aCBhIGhpZ2ggY29uY2VudHJhdGlvbiBvZiBzcGVjaWZpYyByb2xlcy4KCkV4YW1pbmluZyB0aGUgZGlzdHJpYnV0aW9uIG9mIGV4cGVyaWVuY2UgbGV2ZWxzIGFtb25nIGVtcGxveWVlcyBvZmZlcmVkIGluc2lnaHRzIGludG8gdGhlIHdvcmtmb3JjZSBjb21wb3NpdGlvbiwgd2l0aCBhIG5vdGFibGUgcHJlc2VuY2Ugb2YgbWlkLWxldmVsIGFuZCBzZW5pb3ItbGV2ZWwgcG9zaXRpb25zLiBUaGlzIGRpc3RyaWJ1dGlvbiByZWZsZWN0cyB0aGUgbWF0dXJpdHkgYW5kIGV4cGVydGlzZSBvZiB0aGUgd29ya2ZvcmNlLCBlc3NlbnRpYWwgZm9yIHVuZGVyc3RhbmRpbmcgdGFsZW50IGRlbW9ncmFwaGljcyBhbmQgcGxhbm5pbmcgb3JnYW5pemF0aW9uYWwgc3RyYXRlZ2llcy4KClRoZSBhbmFseXNpcyBvZiBhdmVyYWdlIHNhbGFyeSB0cmVuZHMgb3ZlciB0aGUgeWVhcnMgdW52ZWlsZWQgYSBwb3NpdGl2ZSB0cmFqZWN0b3J5LCB3aXRoIHNhbGFyaWVzIGV4cGVyaWVuY2luZyBhIHN0ZWFkeSBpbmNyZWFzZSBvdmVyIHRpbWUuIFRoaXMgZ3Jvd3RoIHJlZmxlY3RzIGJyb2FkZXIgZWNvbm9taWMgY29uZGl0aW9ucywgaW5kdXN0cnkgZGVtYW5kLCBhbmQgZXZvbHZpbmcgc2tpbGwgcmVxdWlyZW1lbnRzIGNvbnRyaWJ1dGluZyB0byBzYWxhcnkgZXNjYWxhdGlvbnMgYWNyb3NzIGRpZmZlcmVudCBqb2Igcm9sZXMgYW5kIHJlZ2lvbnMuCgpUaGUgZXhhbWluYXRpb24gb2Ygc2FsYXJ5IGRpc3RyaWJ1dGlvbnMgYnkgam9iIHRpdGxlIGFuZCBleHBlcmllbmNlIGxldmVsIHByb3ZpZGVkIGEgbnVhbmNlZCB1bmRlcnN0YW5kaW5nIG9mIGNvbXBlbnNhdGlvbiBzdHJ1Y3R1cmVzIHdpdGhpbiB0aGUgaW5kdXN0cnkuIFJvbGVzIHN1Y2ggYXMgSGVhZCBvZiBEYXRhLCBSZXNlYXJjaCBFbmdpbmVlciwgYW5kIEFJIERldmVsb3BlciBlbWVyZ2VkIHdpdGggbm90YWJsZSBzYWxhcnkgdmFyaWF0aW9ucywgaW5kaWNhdGl2ZSBvZiB0aGUgZGl2ZXJzZSBza2lsbHNldHMgYW5kIHJlc3BvbnNpYmlsaXRpZXMgYXNzb2NpYXRlZCB3aXRoIHRoZXNlIHBvc2l0aW9ucy4gQWRkaXRpb25hbGx5LCB0aGUgYW5hbHlzaXMgaGlnaGxpZ2h0ZWQgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZXMgaW4gc2FsYXJpZXMgYWNyb3NzIGV4cGVyaWVuY2UgbGV2ZWxzLCBlbXBoYXNpemluZyB0aGUgaW1wb3J0YW5jZSBvZiBleHBlcnRpc2UgYW5kIHNlbmlvcml0eSBpbiBkcml2aW5nIGNvbXBlbnNhdGlvbiBsZXZlbHMuCgpGaW5hbGx5LCB0aGUgdHJlZW1hcCB2aXN1YWxpemF0aW9uIG9mZmVyZWQgYSBjb21wcmVoZW5zaXZlIHZpZXcgb2YgYXZlcmFnZSBzYWxhcnkgZGlzdHJpYnV0aW9ucyBhY3Jvc3MgZW1wbG95ZWUgcmVzaWRlbmNlcyBhbmQgam9iIHRpdGxlcywgaGlnaGxpZ2h0aW5nIGx1Y3JhdGl2ZSByb2xlcyBhbmQgcmVnaW9ucyB3aXRoaW4gdGhlIGluZHVzdHJ5LiBCeSBmb2N1c2luZyBvbiB0aGUgZGF0YSBzY2llbnRpc3Qgcm9sZSwgd2Ugb2JzZXJ2ZWQgYSBzdWJ0bGUgeWV0IGRpc2Nlcm5pYmxlIGluY3JlYXNlIGluIHNhbGFyeSBvdmVyIHRoZSB5ZWFycywgaW5kaWNhdGluZyBzdGFibGUgb3IgbW9kZXN0IGdyb3d0aCBpbiBjb21wZW5zYXRpb24gZm9yIHByb2Zlc3Npb25hbHMgd2l0aGluIHRoaXMgZG9tYWluLgoKSW4gY29uY2x1c2lvbiwgdGhpcyBhbmFseXNpcyBwcm92aWRlcyB2YWx1YWJsZSBpbnNpZ2h0cyBmb3IgaW5kdXN0cnkgc3Rha2Vob2xkZXJzLCBwb2xpY3ltYWtlcnMsIGFuZCBwcm9mZXNzaW9uYWxzIHNlZWtpbmcgdG8gdW5kZXJzdGFuZCBzYWxhcnkgZHluYW1pY3MsIHdvcmtmb3JjZSB0cmVuZHMsIGFuZCByZWdpb25hbCB2YXJpYXRpb25zIHdpdGhpbiB0aGUgZmllbGQuIEJ5IGxldmVyYWdpbmcgaW50ZXJhY3RpdmUgdmlzdWFsaXphdGlvbnMgYW5kIHN0YXRpc3RpY2FsIGFuYWx5c2VzLCB3ZSBoYXZlIHNoZWQgbGlnaHQgb24ga2V5IGZhY3RvcnMgc2hhcGluZyBjb21wZW5zYXRpb24gdHJlbmRzLCBvZmZlcmluZyBhIHJvYnVzdCBmb3VuZGF0aW9uIGZvciBpbmZvcm1lZCBkZWNpc2lvbi1tYWtpbmcgYW5kIHN0cmF0ZWdpYyBwbGFubmluZyBpbiB0aGUgZXZlci1ldm9sdmluZyBsYW5kc2NhcGUgb2YgdGhlIGluZHVzdHJ5LgoKCgoKCg==